﻿using LinqToExcel.Attributes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Win.CSkin.Test
{
    public static class CommonObject
    {
        public static List<DPS_StorageCheckInfo> DPS_Current_StorageChecks = new List<DPS_StorageCheckInfo>();

        public static ConcurrentBag<DPS_StorageCheckInfo> DPS_Current_StorageCheckBags = new ConcurrentBag<DPS_StorageCheckInfo>();

        /// <summary>
        /// 当前各层盘点数量状态队列
        /// </summary>
        public static List<DPS_LayCheckInfo> DPS_Current_StorageChecksNew = new List<DPS_LayCheckInfo>();
    }

    /// <summary>
    /// 层盘点信息
    /// </summary>
    public class DPS_LayCheckInfo
    {
        /// <summary>
        /// 层
        /// </summary>
        public int Check_Lay { get; set; }
        /// <summary>
        /// 当前层是否已盘点
        /// </summary>
        public bool IsLayChecked { get; set; } = false;
        /// <summary>
        /// 各单元格盘点详情
        /// </summary>
        public List<DPS_StorageCheckInfo> UnitCheckInfos { get; set; }
    }

    /// <summary>
    /// 存储单元盘点数据
    /// </summary>
    public class DPS_StorageCheckInfo
    {
        /// <summary>
        /// 层
        /// </summary>
        public int Storage_Lay { get; set; }
        /// <summary>
        /// 储位列号（已算上药架）
        /// </summary>
        public int Storage_Column { get; set; }
        /// <summary>
        /// 药盒编号
        /// </summary>
        public string Storage_BoxID { get; set; }
        /// <summary>
        /// 单元格
        /// </summary>
        public int Storage_UnitID { get; set; }
        /// <summary>
        /// 单元格药品
        /// </summary>
        public string Storage_DrugID { get; set; }
        /// <summary>
        /// 单元格药品
        /// </summary>
        public string Storage_DrugName { get; set; }
        /// <summary>
        /// 药品直径 
        /// </summary>
        public int Storage_Drug_Diameter { get; set; }
        /// <summary>
        /// 单元格盘点数量
        /// </summary>
        public int Storage_CheckNum { get; set; }
        /// <summary>
        /// 单元格盘点状态
        /// </summary>
        public int Storage_CheckStatus { get; set; }

        /// <summary>
        /// 单元格数量是否已更新DB
        /// </summary>
        public bool DB_Update_Status { get; set; } = false;

        /// <summary>
        /// 单元格数量是否已更新PLC
        /// </summary>
        public bool PLC_Update_Status { get; set; } = false;

        /// <summary>
        /// 盘点信息描述
        /// </summary>
        public string Check_Desc { get; set; }
    }

    public class ClassPropertyInfo
    {
        public string PropertyName { get; set; }

        public string PropertyNameDescription { get; set; }

        public string PropertyNameSuggest { get; set; }

        public object PropertyValue { get; set; }

        public Type PropertyType { get; set; }
    }

    public class TestAttributeModel
    {
        [Description("test1故障"), Suggest("测试1")]
        public bool test1
        {
            get; set;
        }

        [Description("test2故障"), Suggest("测试2")]
        public bool test2
        {
            get; set;
        }

        /// <summary>
        /// NC0模块故障
        /// </summary>
        [Description("NC0模块故障"), Suggest("")]
        public bool NC0_PCU_Fault
        {
            get; set;
        }
        /// <summary>
        /// NC2模块故障
        /// </summary>
        [Description("NC2模块故障"), Suggest("")]
        public bool NC2_PCU_Fault
        {
            get; set;
        }
    }

    /// <summary>
    /// 发行任务数据
    /// </summary>
    public class DPS_IssueData_LabelInfo
    {
        List<DPS_IssueData_LabelDetailInfo> _DrugsInfo = new List<DPS_IssueData_LabelDetailInfo>();
        public List<DPS_IssueData_LabelDetailInfo> IssueData_DrugsInfo
        {
            get { return _DrugsInfo; }
            set { _DrugsInfo = value; }
        }

        public List<DPS_IssueData_LabelDetailInfo> IssueData_DrugsInfo_Print { get; set; } = new List<DPS_IssueData_LabelDetailInfo>();
    }
    /// <summary>
    /// 发行任务明细数据
    /// </summary>
    public class DPS_IssueData_LabelDetailInfo
    {
        /// <summary>
        /// 标签信息
        /// </summary>
        public string IssueData_LabelID
        {
            get;
            set;
        }
        /// <summary>
        /// 药品ID
        /// </summary>
        public string IssueData_DrugCode
        {
            get; set;
        }
        /// <summary>
        /// 药品名称
        /// </summary>
        public string IssueData_DrugName { get; set; }
        /// <summary>
        /// 发药数量
        /// </summary>
        public int IssueData_DrugNum
        {
            get; set;
        }
        /// <summary>
        /// 发药数量
        /// </summary>
        public int IssueData_DrugNum_Print
        {
            get; set;
        }

        /// <summary>
        /// 药品备注
        /// </summary>
        public string IssueData_DrugAddInfo { get; set; }

        /// <summary>
        /// Double:容积
        /// </summary>                       
        public Double IssueData_DrugCapacity { get; set; }
        /// <summary>
        /// String:
        /// </summary>                       
        public String IssueData_DrugSpec { get; set; }

        /// <summary>
        /// Double:
        /// </summary>                       
        public Double IssueData_DosageAmt { get; set; }

        /// <summary>
        /// 
        /// </summary>                       
        public string IssueData_DosageUnit { get; set; }

        /// <summary>
        /// 
        /// </summary>                       
        public string IssueData_CheckerName { get; set; }
    }

    [XmlRoot("WaWi")]
    public class WaWi
    {
        //[XmlElement("AMsg")]
        public AMsg AMsg { get; set; } = new AMsg();
    }

    [XmlRoot("AMsg")]
    public class AMsg
    {
        [XmlAttribute]
        public string RequesterNumber { get; set; }

        [XmlAttribute]
        public string OrderNumber { get; set; }

        [XmlAttribute]
        public string OutputNumber { get; set; }

        [XmlAttribute]
        public string Priority { get; set; }

        //加上[XmlElement("Record")]后，生成xml时会去掉套在Record外面的Records这一层
        [XmlElement("Record")]
        public List<Record> Records { get; set; } = new List<Record>();

    }

    //[XmlRoot("Record")]
    public class Record
    {
        [XmlAttribute]
        public string Country { get; set; }
        [XmlAttribute]
        public string Code { get; set; }
        [XmlAttribute]
        public string BarCode { get; set; }
        [XmlAttribute]
        public string Quantity { get; set; }
        [XmlAttribute]
        public string BatchNumber { get; set; }
        [XmlAttribute]
        public string ExternalIdCode { get; set; }
        [XmlAttribute]
        public string Date { get; set; }
    }

    [XmlRoot("root")]
    public class beijing3
    {
        public commitdata commitdata = new commitdata();

        public returndata returndata = new returndata();

        public operateinfo operateinfo = new operateinfo();

        public result result = new result();
    }

    public class commitdata
    {
        public List<datarow> data { get; set; } = new List<datarow>();
    }

    public class returndata
    {
        public List<datarow> data { get; set; } = new List<datarow>();
    }

    public class datarow
    {
        [XmlAttribute]
        public string drug_code { get; set; }
        [XmlAttribute]
        public string sub_code { get; set; }
        [XmlAttribute]
        public string drugname { get; set; }
        [XmlAttribute]
        public string specification { get; set; }
        [XmlAttribute]
        public string fy_unit { get; set; }
        [XmlAttribute]
        public string pack_unit { get; set; }
        [XmlAttribute]
        public string yp_ratio { get; set; }
        [XmlAttribute]
        public string py_code { get; set; }
        [XmlAttribute]
        public string manu_code { get; set; }
        [XmlAttribute]
        public string retprice { get; set; }
        [XmlAttribute]
        public string group_no { get; set; }
    }

    public class operateinfo
    {
        public info info = new info();
    }

    public class result
    {
        public info info = new info();
    }

    public class info
    {
        [XmlAttribute]
        public string method { get; set; }
        [XmlAttribute]
        public string opt_id { get; set; }
        [XmlAttribute]
        public string opt_name { get; set; }
        [XmlAttribute]
        public string opt_date { get; set; }
        [XmlAttribute]
        public string guid { get; set; }
        [XmlAttribute]
        public string token { get; set; }

        [XmlAttribute]
        public string execute_flag { get; set; }
        [XmlAttribute]
        public string execute_message { get; set; }
        [XmlAttribute]
        public string account { get; set; }
    }

    public class MedModel
    {
        public string MedCode { get; set; }
        public string MedName { get; set; }
    }

    public class MedPresInfo
    {
        [XmlElement("Med")]
        public List<MedModel> MedListModel { get; set; } = new List<MedModel>();
    }

    /// <summary>
    /// 导入模板对象
    /// </summary>
    public class ImportReport
    {
        [ExcelColumn("药品编码")]
        public string DrugCode { get; set; }
        [ExcelColumn("批号/效期")]
        public string BatchNValid { get; set; }
    }

    #region property

    public class CCountry
    {
        public CCountry(string name, List<CProvince> proList, CProvince pro)
        {
            _ProvinceList = proList;
            _Province = pro;
            _Name = name;
        }

        private string _Name;
        [Category("国家")]
        [DisplayName("名称")]
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private List<CProvince> _ProvinceList;
        [Category("国家")]
        [DisplayName("省份")]
        //[TypeConverter(typeof(ConverterPro))]
        public List<CProvince> ProvinceList
        {
            get { return _ProvinceList; }
            set { _ProvinceList = value; }
        }

        private CProvince _Province;
        [Category("国家")]
        [DisplayName("省份")]
        //[TypeConverter(typeof(ConverterPro))]
        public CProvince Province
        {
            get { return _Province; }
            set { _Province = value; }
        }
    }

    [TypeConverter(typeof(ConverterPro))]
    public class CProvince
    {
        public CProvince(string name, CProvincialCapital provincialCapital, int district)
        {
            _Name = name;
            _ProvincialCapital = provincialCapital;
            _District = district;
        }

        private string _Name;
        [DisplayName("名称")]
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private CProvincialCapital _ProvincialCapital;
        [DisplayName("省会")]
        public CProvincialCapital ProvincialCapital
        {
            get { return _ProvincialCapital; }
            set { _ProvincialCapital = value; }
        }

        private int _District;
        [DisplayName("地区数量")]
        public int District
        {
            get { return _District; }
            set { _District = value; }
        }
    }

    [TypeConverter(typeof(ConverterProCap))]
    public class CProvincialCapital
    {
        public CProvincialCapital(string name, int population)
        {
            _Name = name;
            _Population = population;
        }

        private string _Name;
        [DisplayName("名称")]
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private int _Population;
        [DisplayName("人口数量")]
        public int Population
        {
            get { return _Population; }
            set { _Population = value; }
        }
    }

    public class ConverterPro : ExpandableObjectConverter
    {
        /// <summary>
        /// 返回该转换器是否可以使用指定的上下文将该对象转换为指定的类型
        /// </summary>
        /// <param name="context"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(CProvince))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        /// <summary>
        /// 返回该转换器是否可以使用指定的上下文将给定类型的对象转换为此转换器的类型
        /// </summary>
        /// <param name="context">提供有关组件的上下文，如其容器和属性描述符</param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        /// <summary>
        /// 使用指定的上下文和区域性信息将给定的值对象转换为指定的类型
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture,
            object value, Type destinationType)
        {
            if (destinationType == typeof(string) &&
                value is CProvince)
            {
                CProvince pro = (CProvince)value;

                //return "";
                return pro.Name + "," + pro.District + "," + pro.ProvincialCapital.Name +
                    "," + pro.ProvincialCapital.Population.ToString();
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }


        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                string s = (string)value;
                string[] ss = s.Split(',');

                CProvincialCapital proCap = new CProvincialCapital(ss[1].ToString(), int.Parse(ss[2]));
                CProvince pro = new CProvince(ss[0].ToString(), proCap, int.Parse(ss[3]));
                //return "";
                return pro;
            }

            return base.ConvertFrom(context, culture, value);
        }
    }

    public class ConverterProCap : ExpandableObjectConverter
    {
        /// <summary>
        /// 返回该转换器是否可以使用指定的上下文将该对象转换为指定的类型
        /// </summary>
        /// <param name="context"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(CProvincialCapital))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        /// <summary>
        /// 返回该转换器是否可以使用指定的上下文将给定类型的对象转换为此转换器的类型
        /// </summary>
        /// <param name="context">提供有关组件的上下文，如其容器和属性描述符</param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        /// <summary>
        /// 使用指定的上下文和区域性信息将给定的值对象转换为指定的类型
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture,
            object value, Type destinationType)
        {
            if (destinationType == typeof(string) &&
                value is CProvincialCapital)
            {
                CProvincialCapital cou = (CProvincialCapital)value;
                string name = cou.Name;
                int population = cou.Population;

                //return "";
                return name.ToString() + "," + population.ToString();
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }


        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                string s = (string)value;
                string[] ss = s.Split(',');

                CProvincialCapital cou = new CProvincialCapital(ss[0].ToString(), int.Parse(ss[1]));
                //return "";
                return cou;
            }

            return base.ConvertFrom(context, culture, value);
        }
    }


    [DefaultProperty("Tables")]
    public class Database
    {
        public Database()
        {
            Name = "NewDatabase";
            Password = string.Empty;
            InitializeCommand = string.Empty;
            if (Tables == null)
            {
                Tables = new List<Table>();
            }
        }

        [Category("属性"),
            DisplayName("数据库名称")]
        public string Name { get; set; }

        [Category("属性"),
            DisplayName("数据库密码")]
        public string Password { get; set; }

        [Category("属性"),
            DisplayName("初始化语句")]
        public string InitializeCommand { get; set; }

        [Category("数据表设置"),
            DisplayName("数据表集合")]
        public List<Table> Tables { get; set; }

        [Description("主键生成方式"), DisplayName("主键生成方式")]
        [TypeConverter(typeof(EnumConverter))]
        public PKGenerator PKGenerator
        {
            get;
            set;
        }
    }

    [DefaultProperty("Columns")]
    public class Table
    {
        public Table()
        {
            Name = "NewTable";
            Comment = string.Empty;
            if (Columns == null)
            {
                Columns = new List<Column>();
            }
        }

        [Category("属性"),
            DisplayName("数据表名称")]
        public string Name { get; set; }

        [Category("数据列设置"),
            DisplayName("数据列集合")]
        public List<Column> Columns { get; set; }

        [Category("属性"),
            DisplayName("备注")]
        public string Comment { get; set; }
    }

    [DefaultProperty("Name")]
    public class Column
    {
        public Column()
        {
            Name = "NewColumn";
            Type = SupportedType.Int32;
            Comment = string.Empty;
            NotNull = true;
        }

        [DisplayName("列名"),
            Category("属性")]
        public string Name { get; set; }

        [DisplayName("类型"),
            Category("属性")]
        public SupportedType Type { get; set; }

        [DisplayName("注释"),
            Category("属性")]
        public string Comment { get; set; }

        [DisplayName("是否是主键"),
            DefaultValue(false),
            Category("属性")]
        public bool IsMainKey { get; set; }

        [DisplayName("是否非空"),
            DefaultValue(true),
            Category("属性")]
        public bool NotNull { get; set; }

        [DisplayName("是否自动增长"),
            DefaultValue(false),
            Category("属性")]
        public bool IsAutoIncrement { get; set; }

        [DisplayName("是否是索引"),
            DefaultValue(false),
            Category("属性")]
        public bool IsIndex { get; set; }
    }

    public enum SupportedType
    {
        Boolean,
        DateTime,
        Decimal,
        Double,
        Int64,
        Int32,
        Int16,
        SByte,
        Single,
        String,
        UInt64,
        UInt32,
        UInt16,
        Byte
    }

    public enum PKGenerator
    {
        /// <summary>
        /// 根据主键类型自动生成主键
        /// </summary>
        [Description("自动生成")]
        AutoGenerate = 0,
        /// <summary>
        /// 自定义主键
        /// </summary>
        [Description("自定义")]
        User_Defined = 1,
        /// <summary>
        /// 由外面传入
        /// </summary>
        [Description("外部传入")]
        Outer = 2
    }

    /// <summary>
    /// 枚举转换器
    /// 用此类之前，必须保证在枚举项中定义了Description
    /// </summary>
    public class EnumConverter : ExpandableObjectConverter
    {
        /// <summary>
        /// 枚举项集合
        /// </summary>
        Dictionary<object, string> dic;

        /// <summary>
        /// 构造函数
        /// </summary>
        public EnumConverter()
        {
            dic = new Dictionary<object, string>();
        }
        /// <summary>
        /// 加载枚举项集合
        /// </summary>
        /// <param name="context"></param>
        private void LoadDic(ITypeDescriptorContext context)
        {
            dic = GetEnumValueDesDic(context.PropertyDescriptor.PropertyType);
        }

        /// <summary>
        /// 是否可从来源转换
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;

            return base.CanConvertFrom(context, sourceType);
        }
        /// <summary>
        /// 从来源转换
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                //如果是枚举
                if (context.PropertyDescriptor.PropertyType.IsEnum)
                {
                    if (dic.Count <= 0)
                        LoadDic(context);
                    if (dic.Values.Contains(value.ToString()))
                    {
                        foreach (object obj in dic.Keys)
                        {
                            if (dic[obj] == value.ToString())
                            {
                                return obj;
                            }
                        }
                    }
                }
            }

            return base.ConvertFrom(context, culture, value);
        }
        /// <summary>
        /// 是否可转换
        /// </summary>
        /// <param name="context"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            //ListAttribute listAttribute = (ListAttribute)context.PropertyDescriptor.Attributes[typeof(ListAttribute)];
            //StandardValuesCollection vals = new TypeConverter.StandardValuesCollection(listAttribute._lst);

            //Dictionary<object, string> dic = GetEnumValueDesDic(typeof(PKGenerator));

            //StandardValuesCollection vals = new TypeConverter.StandardValuesCollection(dic.Keys);

            if (dic == null || dic.Count <= 0)
                LoadDic(context);

            StandardValuesCollection vals = new TypeConverter.StandardValuesCollection(dic.Keys);

            return vals;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            //DescriptionAttribute.GetCustomAttribute(
            //EnumDescription
            //List<KeyValuePair<Enum, string>> mList = UserCombox.ToListForBind(value.GetType());
            //foreach (KeyValuePair<Enum, string> mItem in mList)
            //{
            //    if (mItem.Key.Equals(value))
            //    {
            //        return mItem.Value;
            //    }
            //}
            //return "Error!";

            //绑定控件
            //            FieldInfo fieldinfo = value.GetType().GetField(value.ToString());
            //Object[] objs = fieldinfo.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
            //if (objs == null || objs.Length == 0)
            //{
            //    return value.ToString();
            //}
            //else
            //{
            //    System.ComponentModel.DescriptionAttribute da = (System.ComponentModel.DescriptionAttribute)objs[0];
            //    return da.Description;
            //}

            if (dic.Count <= 0)
                LoadDic(context);

            foreach (object key in dic.Keys)
            {
                if (key.ToString() == value.ToString() || dic[key] == value.ToString())
                {
                    return dic[key].ToString();
                }
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        /// <summary>
        /// 记载枚举的值+描述
        /// </summary>
        /// <param name="enumType"></param>
        /// <returns></returns>
        public Dictionary<object, string> GetEnumValueDesDic(Type enumType)
        {
            Dictionary<object, string> dic = new Dictionary<object, string>();
            FieldInfo[] fieldinfos = enumType.GetFields();
            foreach (FieldInfo field in fieldinfos)
            {
                if (field.FieldType.IsEnum)
                {
                    Object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (objs.Length > 0)
                    {
                        dic.Add(Enum.Parse(enumType, field.Name), ((DescriptionAttribute)objs[0]).Description);
                    }
                }

            }

            return dic;
        }

    }

    #endregion


}
